<template>
  <div class="gitlab-audit-container">
    <!-- 星空背景 -->
    <div class="starry-background">
      <div class="stars"></div>
      <div class="stars2"></div>
      <div class="stars3"></div>
    </div>

    <!-- 透明玻璃容器 -->
    <div class="glass-container">
      <div class="page-header">
        <h2 class="page-title">
          <i class="fa fa-gitlab"></i>
          GitLab集成历史
        </h2>
      </div>

      <!-- 工具栏：操作按钮 -->
      <div class="toolbar-section glass-effect">
        <div class="toolbar-buttons">
          <button class="glass-button" @click="refreshAudit">
            <i class="fa fa-refresh"></i>
            刷新
          </button>
          <button class="glass-button" @click="exportAudit">
            <i class="fa fa-download"></i>
            导出
          </button>
          <button class="glass-button primary" @click="showWebhookConfig">
            <i class="fa fa-cog"></i>
            配置Webhook
          </button>

          <button class="glass-button" @click="syncHistoryData">
            <i class="fa fa-history"></i>
            同步历史
          </button>
        </div>
      </div>

      <!-- 搜索过滤栏 -->
      <div class="filters-section glass-effect">
        <div class="filters-row">
          <div class="filter-item">
            <label>搜索</label>
            <input
              v-model="searchText"
              type="text"
              class="glass-input"
              placeholder="搜索操作描述、用户名..."
            />
          </div>

          <div class="filter-item">
            <label>项目</label>
            <el-select
              v-model="selectedProject"
              placeholder="所有项目"
              class="glass-select"
              clearable
              @change="onProjectChange"
            >
              <el-option label="所有项目" value="" />
              <el-option
                v-for="project in projects"
                :key="project.id"
                :label="`${project.name} (${project.gitlab_server_name})`"
                :value="project.id"
              />
            </el-select>
          </div>

          <div class="filter-item">
            <label>操作类型</label>
            <el-select v-model="selectedOperation" placeholder="所有操作" class="glass-select" clearable>
              <el-option label="所有操作" value="" />
              <el-option label="项目创建" value="gitlab_project_create" />
              <el-option label="项目更新" value="gitlab_project_update" />
              <el-option label="项目删除" value="gitlab_project_delete" />
              <el-option label="代码提交" value="gitlab_commit" />
              <el-option label="代码合并" value="gitlab_merge" />
              <el-option label="标签操作" value="gitlab_tag" />
              <el-option label="流水线" value="gitlab_pipeline" />
              <el-option label="用户同步" value="gitlab_user_sync" />
              <el-option label="服务器测试" value="gitlab_server_test" />
            </el-select>
          </div>

          <div class="filter-item">
            <label>结果</label>
            <el-select v-model="selectedResult" placeholder="所有结果" class="glass-select" clearable>
              <el-option label="所有结果" value="" />
              <el-option label="成功" value="success" />
              <el-option label="失败" value="failed" />
            </el-select>
          </div>

          <div class="filter-item">
            <label>开始日期</label>
            <el-date-picker
              v-model="dateRange.start"
              type="date"
              placeholder="选择开始日期"
              class="glass-date-picker"
              format="YYYY-MM-DD"
              value-format="YYYY-MM-DD"
            />
          </div>

          <div class="filter-item">
            <label>结束日期</label>
            <el-date-picker
              v-model="dateRange.end"
              type="date"
              placeholder="选择结束日期"
              class="glass-date-picker"
              format="YYYY-MM-DD"
              value-format="YYYY-MM-DD"
            />
          </div>
        </div>
      </div>

      <!-- Git提交图表 -->
      <div class="git-graph-section glass-effect">
        <div class="section-header">
          <h3>
            <i class="fa fa-code-branch"></i>
            Git提交图表
          </h3>
          <div class="graph-controls">
            <button
              class="glass-button"
              @click="loadProjectGitGraph"
              :disabled="isLoadingGraph || !selectedProject"
            >
              <i class="fa fa-refresh" :class="{ 'fa-spin': isLoadingGraph }"></i>
              {{ isLoadingGraph ? '加载中...' : '刷新图表' }}
            </button>
          </div>
        </div>

        <div class="git-graph-container">
          <div v-if="isLoadingGraph" class="loading-state">
            <i class="fa fa-spinner fa-spin"></i>
            正在加载Git图表...
          </div>

          <div v-else-if="!selectedProject" class="empty-state">
            <i class="fa fa-info-circle empty-icon"></i>
            <h4>请选择项目</h4>
            <p>选择上方的项目后，将自动显示该项目的Git提交图表</p>
          </div>

          <div v-else-if="gitCommits.length === 0" class="empty-state">
            <i class="fa fa-code-branch empty-icon"></i>
            <h4>暂无提交记录</h4>
            <p>该项目暂无Git提交记录，或者数据正在同步中</p>
          </div>

          <div v-else class="git-graph-content">
            <div class="git-graph" ref="gitGraphRef">
              <!-- Git图表将在这里渲染 -->
            </div>
          </div>
        </div>
      </div>

      <!-- 审计日志表格 -->
      <div class="audit-table" style="margin-bottom: 100px; max-height: calc(100vh - 350px); overflow-y: auto;">
        <div class="table-header">
          <div class="header-cell time-header">时间</div>
          <div class="header-cell operation-header">操作类型</div>
          <div class="header-cell user-header">操作用户</div>
          <div class="header-cell target-header">目标对象</div>
          <div class="header-cell project-header">项目</div>
          <div class="header-cell result-header">结果</div>
          <div class="header-cell action-header">操作</div>
        </div>

        <div class="table-body">
          <div
            v-for="audit in filteredAudits"
            :key="audit.id"
            class="table-row"
            :class="{ 'row-success': audit.result === 'success', 'row-failed': audit.result === 'failed' }"
          >
            <div class="table-cell">
              <div class="time-info">
                <div class="time-primary">{{ formatDate(audit.created_at) }}</div>
                <div class="time-secondary">{{ formatTime(audit.created_at) }}</div>
              </div>
            </div>

            <div class="table-cell">
              <div class="operation-info">
                <span
                  class="operation-badge"
                  :class="getOperationClass(audit.operation_type)"
                >
                  {{ getOperationText(audit.operation_type) }}
                </span>
              </div>
            </div>

            <div class="table-cell">
              <div class="user-info">
                <div class="username">{{ getUserDisplayName(audit) }}</div>
                <div class="user-name">{{ getUserRealName(audit) }}</div>
              </div>
            </div>

            <div class="table-cell">
              <div class="target-info">
                <div class="target-name">{{ audit.target_name }}</div>
                <div class="target-type">{{ audit.target_type }}</div>
              </div>
            </div>

            <div class="table-cell">
              <div class="project-info">
                <span class="project-name">{{ audit.gitlab_project_name || '-' }}</span>
                <div class="project-path">{{ audit.gitlab_project_path }}</div>
              </div>
            </div>

            <div class="table-cell">
              <span
                class="result-badge"
                :class="{ 'result-success': audit.result === 'success', 'result-failed': audit.result === 'failed' }"
              >
                {{ audit.result === 'success' ? '成功' : '失败' }}
              </span>
            </div>

            <div class="table-cell">
              <div class="action-buttons">
                <button class="glass-button small" @click="viewDetails(audit)">
                  <i class="fa fa-eye"></i>
                  详情
                </button>
                <!-- GitLab按钮暂时隐藏，因为无法获取到正确的GitLab地址 -->
                <!--
                <button
                  v-if="audit.gitlab_project"
                  class="glass-button small"
                  @click="openGitLab(audit)"
                >
                  <i class="fa fa-external-link"></i>
                  GitLab
                </button>
                -->
              </div>
            </div>
          </div>
        </div>

        <!-- 空状态 -->
        <div v-if="filteredAudits.length === 0" class="empty-state">
          <i class="fa fa-file-text empty-icon"></i>
          <h3>暂无审计记录</h3>
          <p>在选定的条件下没有找到相关的GitLab操作记录</p>
        </div>
      </div>

      <!-- 分页 -->
      <div v-if="pagination.total > 0" class="pagination">
        <div class="pagination-info">
          共 {{ pagination.total }} 条记录，第 {{ pagination.current }} / {{ Math.ceil(pagination.total / pagination.pageSize) }} 页
        </div>
        <div class="pagination-controls">
          <button
            class="glass-button small"
            @click="changePage(pagination.current - 1)"
            :disabled="pagination.current <= 1"
          >
            <i class="fa fa-chevron-left"></i>
            上一页
          </button>
          <button
            class="glass-button small"
            @click="changePage(pagination.current + 1)"
            :disabled="pagination.current >= Math.ceil(pagination.total / pagination.pageSize)"
          >
            下一页
            <i class="fa fa-chevron-right"></i>
          </button>
        </div>
      </div>
    </div>

    <!-- 详情模态框 -->
    <div v-if="detailModalVisible" class="modal-overlay" @click="closeDetailModal">
      <div class="modal-content glass-container" @click.stop>
        <div class="modal-header">
          <h3>操作详情</h3>
          <button class="close-btn" @click="closeDetailModal">
            <i class="fa fa-times"></i>
          </button>
        </div>

        <div class="audit-detail-content">
          <div class="detail-section">
            <h4>基本信息</h4>
            <div class="detail-grid">
              <div class="detail-item">
                <span class="label">操作时间:</span>
                <span class="value">{{ formatDateTime(selectedAudit?.created_at) }}</span>
              </div>
              <div class="detail-item">
                <span class="label">操作类型:</span>
                <span class="value">{{ getOperationText(selectedAudit?.operation_type) }}</span>
              </div>
              <div class="detail-item">
                <span class="label">操作用户:</span>
                <span class="value">{{ selectedAudit?.user?.username || '系统' }}</span>
              </div>
              <div class="detail-item">
                <span class="label">目标对象:</span>
                <span class="value">{{ selectedAudit?.target_name }}</span>
              </div>
              <div class="detail-item">
                <span class="label">目标类型:</span>
                <span class="value">{{ selectedAudit?.target_type }}</span>
              </div>
              <div class="detail-item">
                <span class="label">操作结果:</span>
                <span class="value">{{ selectedAudit?.result === 'success' ? '成功' : '失败' }}</span>
              </div>
            </div>
          </div>

          <div class="detail-section" v-if="selectedAudit?.error_message">
            <h4>错误信息</h4>
            <div class="error-message">
              {{ selectedAudit.error_message }}
            </div>
          </div>

          <div class="detail-section" v-if="selectedAudit?.operation_data">
            <h4>操作数据</h4>
            <pre class="detail-json">{{ JSON.stringify(selectedAudit.operation_data, null, 2) }}</pre>
          </div>
        </div>
      </div>
    </div>

    <!-- Webhook配置弹窗 -->
    <div v-if="webhookModalVisible" class="modal-overlay" @click="closeWebhookModal">
      <div class="modal-content glass-effect" @click.stop>
        <div class="modal-header">
          <h3>
            <i class="fa fa-cog"></i>
            配置GitLab Webhook
          </h3>
          <button class="close-btn" @click="closeWebhookModal">
            <i class="fa fa-times"></i>
          </button>
        </div>

        <div class="modal-body">
          <div class="webhook-info">
            <h4>自动配置Webhook</h4>
            <p>系统将自动为您的GitLab项目配置Webhook，以便实时接收以下事件：</p>
            <ul>
              <li><i class="fa fa-code"></i> 代码推送事件</li>
              <li><i class="fa fa-code-fork"></i> 合并请求事件</li>
              <li><i class="fa fa-tag"></i> 标签推送事件</li>
              <li><i class="fa fa-cogs"></i> 流水线事件</li>
            </ul>
          </div>

          <div class="server-selection">
            <label>选择GitLab服务器：</label>
            <el-select v-model="selectedWebhookServer" placeholder="请选择GitLab服务器" class="glass-select">
              <el-option
                v-for="server in gitlabServers"
                :key="server.id"
                :label="server.name"
                :value="server.id"
              />
            </el-select>
          </div>

          <div class="webhook-url-info">
            <label>Webhook URL：</label>
            <div class="url-display">
              <input
                type="text"
                :value="webhookUrl"
                readonly
                class="glass-input"
              />
              <button class="glass-button small" @click="copyWebhookUrl">
                <i class="fa fa-copy"></i>
                复制
              </button>
            </div>
          </div>

          <div class="webhook-actions">
            <button
              class="glass-button primary"
              @click="autoConfigureWebhook"
              :disabled="!selectedWebhookServer || isConfiguringWebhook"
            >
              <i class="fa fa-magic"></i>
              {{ isConfiguringWebhook ? '配置中...' : '自动配置所有项目' }}
            </button>
            <button class="glass-button" @click="showManualConfig = !showManualConfig">
              <i class="fa fa-book"></i>
              手动配置说明
            </button>
          </div>

          <div v-if="showManualConfig" class="manual-config">
            <h4>手动配置步骤：</h4>
            <ol>
              <li>登录您的GitLab</li>
              <li>进入项目设置 → Webhooks</li>
              <li>添加新的Webhook，URL填写：<code>{{ webhookUrl }}</code></li>
              <li>勾选以下触发器：
                <ul>
                  <li>Push events</li>
                  <li>Tag push events</li>
                  <li>Merge request events</li>
                  <li>Pipeline events</li>
                </ul>
              </li>
              <li>点击"Add webhook"保存</li>
            </ol>
          </div>

          <div v-if="webhookResults.length > 0" class="webhook-results">
            <h4>配置结果：</h4>
            <div
              v-for="result in webhookResults"
              :key="result.project_id"
              class="result-item"
              :class="{ 'success': result.success, 'error': !result.success }"
            >
              <i :class="result.success ? 'fa fa-check' : 'fa fa-times'"></i>
              <span>{{ result.project_name }}: {{ result.message }}</span>
            </div>
          </div>
        </div>
      </div>
    </div>


  </div>
</template>

<script setup lang="ts">
import { gitlabAuditApi, gitlabProjectApi, gitlabServerApi } from '@/api/gitlab'
import { ElDatePicker, ElMessage, ElOption, ElSelect } from 'element-plus'
import { computed, nextTick, onMounted, ref, watch } from 'vue'

// 响应式数据
const audits = ref([])
const projects = ref([])
const gitlabServers = ref([])
const searchText = ref('')
const selectedProject = ref('')
const selectedOperation = ref('')
const selectedResult = ref('')
const dateRange = ref({
  start: '',
  end: ''
})
const detailModalVisible = ref(false)
const selectedAudit = ref(null)
const pagination = ref({
  current: 1,
  pageSize: 20,
  total: 0
})

// Webhook配置相关
const webhookModalVisible = ref(false)
const selectedWebhookServer = ref('')
const isConfiguringWebhook = ref(false)
const showManualConfig = ref(false)
const webhookResults = ref([])
const webhookUrl = computed(() => {
  const baseUrl = window.location.origin
  return `${baseUrl}/api/gitlab/webhook/`
})

// Git图表相关
const gitCommits = ref([])
const selectedCommit = ref(null)
const isLoadingGraph = ref(false)
const gitGraphRef = ref(null)

// 计算属性
const filteredAudits = computed(() => {
  let filtered = audits.value

  // 搜索过滤
  if (searchText.value) {
    const search = searchText.value.toLowerCase()
    filtered = filtered.filter(audit =>
      audit.target_name.toLowerCase().includes(search) ||
      audit.user?.username.toLowerCase().includes(search) ||
      getOperationText(audit.operation_type).toLowerCase().includes(search)
    )
  }

  // 项目过滤
  if (selectedProject.value) {
    filtered = filtered.filter(audit => audit.gitlab_project == selectedProject.value)
  }

  // 操作类型过滤
  if (selectedOperation.value) {
    filtered = filtered.filter(audit => audit.operation_type === selectedOperation.value)
  }

  // 结果过滤
  if (selectedResult.value) {
    filtered = filtered.filter(audit => audit.result === selectedResult.value)
  }

  // 日期范围过滤
  if (dateRange.value.start) {
    filtered = filtered.filter(audit =>
      new Date(audit.created_at) >= new Date(dateRange.value.start)
    )
  }

  if (dateRange.value.end) {
    filtered = filtered.filter(audit =>
      new Date(audit.created_at) <= new Date(dateRange.value.end + ' 23:59:59')
    )
  }

  return filtered.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())
})

// 方法
const refreshAudit = async () => {
  await loadAudits()
}

const exportAudit = () => {
  try {
    // 准备导出数据
    const exportData = filteredAudits.value.map(audit => ({
      '操作时间': formatDateTime(audit.created_at),
      '操作类型': getOperationText(audit.operation_type),
      '操作用户': audit.user?.username || '系统',
      '用户姓名': `${audit.user?.first_name || ''} ${audit.user?.last_name || ''}`.trim(),
      '目标对象': audit.target_name,
      '关联项目': audit.gitlab_project?.name || '-',
      '操作结果': audit.result === 'success' ? '成功' : '失败',
      '操作描述': audit.description,
      '错误信息': audit.error_message || '-'
    }))

    // 转换为CSV格式
    const headers = Object.keys(exportData[0] || {})
    const csvContent = [
      headers.join(','),
      ...exportData.map(row => headers.map(header => `"${row[header] || ''}"`).join(','))
    ].join('\n')

    // 创建下载链接
    const blob = new Blob(['\ufeff' + csvContent], { type: 'text/csv;charset=utf-8;' })
    const link = document.createElement('a')
    const url = URL.createObjectURL(blob)
    link.setAttribute('href', url)
    link.setAttribute('download', `gitlab_audit_${new Date().toISOString().split('T')[0]}.csv`)
    link.style.visibility = 'hidden'
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)

    ElMessage.success('GitLab审计日志导出成功')
  } catch (error) {
    console.error('导出失败:', error)
    ElMessage.error('导出失败')
  }
}

const viewDetails = (audit: any) => {
  selectedAudit.value = audit
  detailModalVisible.value = true
}

const closeDetailModal = () => {
  detailModalVisible.value = false
  selectedAudit.value = null
}

const openGitLab = (audit: any) => {
  try {
    console.log('打开GitLab链接，audit数据:', audit)

    // 检查是否有GitLab项目信息
    if (!audit.gitlab_project && !audit.project_name) {
      ElMessage.warning('该操作没有关联的GitLab项目')
      return
    }

    // 获取GitLab服务器URL
    let serverUrl = ''
    if (audit.gitlab_server?.url) {
      serverUrl = audit.gitlab_server.url
    } else if (audit.details?.gitlab_server_url) {
      serverUrl = audit.details.gitlab_server_url
    } else {
      ElMessage.warning('无法获取GitLab服务器地址')
      return
    }

    // 构建GitLab链接
    let gitlabUrl = ''
    let projectPath = ''

    // 获取项目路径
    if (audit.gitlab_project?.path_with_namespace) {
      projectPath = audit.gitlab_project.path_with_namespace
    } else if (audit.gitlab_project?.name) {
      projectPath = audit.gitlab_project.name
    } else if (audit.project_name) {
      projectPath = audit.project_name
    }

    if (!projectPath) {
      ElMessage.warning('无法获取项目路径')
      return
    }

    // 根据操作类型构建不同的链接
    if (audit.operation_type === 'gitlab_commit' && audit.details?.commit_id) {
      // 提交链接
      gitlabUrl = `${serverUrl}/${projectPath}/-/commit/${audit.details.commit_id}`
    } else if (audit.operation_type === 'gitlab_merge' && audit.details?.merge_request_iid) {
      // 合并请求链接
      gitlabUrl = `${serverUrl}/${projectPath}/-/merge_requests/${audit.details.merge_request_iid}`
    } else if (audit.operation_type === 'gitlab_tag' && audit.details?.tag_name) {
      // 标签链接
      gitlabUrl = `${serverUrl}/${projectPath}/-/tags/${audit.details.tag_name}`
    } else {
      // 项目主页链接
      gitlabUrl = `${serverUrl}/${projectPath}`
    }

    console.log('构建的GitLab链接:', gitlabUrl)

    if (gitlabUrl) {
      window.open(gitlabUrl, '_blank')
    } else {
      ElMessage.warning('无法构建GitLab链接')
    }
  } catch (error) {
    console.error('打开GitLab链接失败:', error)
    ElMessage.error('打开GitLab链接失败')
  }
}

const changePage = (page: number) => {
  pagination.value.current = page
  loadAudits()
}

const getOperationClass = (operationType: string) => {
  const operationClasses = {
    'gitlab_project_create': 'op-create',
    'gitlab_project_update': 'op-update',
    'gitlab_project_delete': 'op-delete',
    'gitlab_commit': 'op-commit',
    'gitlab_merge': 'op-merge',
    'gitlab_tag': 'op-tag',
    'gitlab_pipeline': 'op-pipeline',
    'gitlab_user_sync': 'op-sync',
    'gitlab_server_test': 'op-test'
  }
  return operationClasses[operationType] || 'op-default'
}

const getOperationText = (operationType: string) => {
  const operationTexts = {
    'gitlab_project_create': '项目创建',
    'gitlab_project_update': '项目更新',
    'gitlab_project_delete': '项目删除',
    'gitlab_commit': '代码提交',
    'gitlab_merge': '代码合并',
    'gitlab_tag': '标签操作',
    'gitlab_pipeline': '流水线',
    'gitlab_user_sync': '用户同步',
    'gitlab_server_test': '服务器测试'
  }
  return operationTexts[operationType] || operationType
}

const formatDate = (dateString: string) => {
  if (!dateString) return '-'
  return new Date(dateString).toLocaleDateString('zh-CN')
}

const formatTime = (dateString: string) => {
  if (!dateString) return '-'
  return new Date(dateString).toLocaleTimeString('zh-CN')
}

const formatDateTime = (dateString: string) => {
  if (!dateString) return '-'
  return new Date(dateString).toLocaleString('zh-CN')
}

// 用户显示逻辑
const getUserDisplayName = (audit: any) => {
  // 如果有平台用户映射，显示平台用户名
  if (audit.user_username) {
    return audit.user_username
  }

  // 如果没有平台用户映射，但有GitLab操作详情，显示GitLab用户
  if (audit.details) {
    // 优先显示GitLab用户名
    if (audit.details.gitlab_user) {
      return `${audit.details.gitlab_user} (GitLab)`
    }
    // 其次显示作者名称
    if (audit.details.author_name) {
      return `${audit.details.author_name} (GitLab)`
    }
    // 最后显示提交者名称
    if (audit.details.committer_name) {
      return `${audit.details.committer_name} (GitLab)`
    }
  }

  return '系统'
}

const getUserRealName = (audit: any) => {
  // 如果有平台用户映射，显示平台用户真实姓名
  if (audit.user_first_name || audit.user_last_name) {
    return `${audit.user_first_name || ''} ${audit.user_last_name || ''}`.trim()
  }

  // 如果没有平台用户映射，显示GitLab邮箱
  if (audit.details) {
    // 优先显示用户邮箱
    if (audit.details.user_email) {
      return audit.details.user_email
    }
    // 其次显示作者邮箱
    if (audit.details.author_email) {
      return audit.details.author_email
    }
    // 最后显示提交者邮箱
    if (audit.details.committer_email) {
      return audit.details.committer_email
    }
  }

  return '自动操作'
}

const loadAudits = async () => {
  try {
    // 构建查询参数
    const params: any = {
      page: pagination.value.current,
      page_size: pagination.value.pageSize
    }

    // 添加过滤条件
    if (selectedProject.value) {
      params.gitlab_project = selectedProject.value
      console.log('过滤项目ID:', selectedProject.value)
    }
    if (selectedOperation.value) {
      params.operation_type = selectedOperation.value
    }
    if (selectedResult.value) {
      params.result = selectedResult.value
    }
    if (dateRange.value.start) {
      params.created_at__gte = dateRange.value.start
    }
    if (dateRange.value.end) {
      params.created_at__lte = dateRange.value.end + ' 23:59:59'
    }
    if (searchText.value) {
      params.search = searchText.value
    }

    console.log('加载审计数据，参数:', params)

    // 调用API获取GitLab审计日志
    const response = await gitlabAuditApi.getAudits(params)
    audits.value = response.data?.results || []
    pagination.value.total = response.data?.count || 0

    console.log('审计数据加载完成:', audits.value.length, '项目过滤:', selectedProject.value)
  } catch (error) {
    console.error('加载GitLab审计日志失败:', error)
    ElMessage.error('加载GitLab审计日志失败')
  }
}

const loadProjects = async () => {
  try {
    // 调用API获取GitLab项目列表
    const response = await gitlabProjectApi.getProjects()
    projects.value = response.data?.results || []
    console.log('加载项目列表成功:', projects.value)
  } catch (error) {
    console.error('加载项目列表失败:', error)
    ElMessage.error('加载项目列表失败')
  }
}

const loadGitLabServers = async () => {
  try {
    // 调用API获取GitLab服务器列表
    const response = await gitlabServerApi.getServers()
    gitlabServers.value = response.data?.results || []
  } catch (error) {
    console.error('加载GitLab服务器列表失败:', error)
    ElMessage.error('加载GitLab服务器列表失败')
  }
}

// Webhook配置相关方法
const showWebhookConfig = () => {
  webhookModalVisible.value = true
  webhookResults.value = []
  showManualConfig.value = false
  loadGitLabServers()
}

const closeWebhookModal = () => {
  webhookModalVisible.value = false
  selectedWebhookServer.value = ''
  webhookResults.value = []
  showManualConfig.value = false
}

const copyWebhookUrl = async () => {
  try {
    await navigator.clipboard.writeText(webhookUrl.value)
    ElMessage.success('Webhook URL已复制到剪贴板')
  } catch (error) {
    ElMessage.error('复制失败，请手动复制')
  }
}

const autoConfigureWebhook = async () => {
  if (!selectedWebhookServer.value) {
    ElMessage.warning('请先选择GitLab服务器')
    return
  }

  isConfiguringWebhook.value = true
  webhookResults.value = []

  try {
    // 调用后端API自动配置Webhook
    const response = await gitlabServerApi.configureWebhooks(selectedWebhookServer.value)

    if (response.data?.success) {
      webhookResults.value = response.data.results || []
      const successCount = webhookResults.value.filter(r => r.success).length
      const totalCount = webhookResults.value.length

      if (successCount === totalCount) {
        ElMessage.success(`成功为 ${successCount} 个项目配置了Webhook`)
      } else {
        ElMessage.warning(`配置完成：${successCount}/${totalCount} 个项目成功`)
      }
    } else {
      ElMessage.error(response.data?.message || '配置Webhook失败')
    }
  } catch (error) {
    console.error('配置Webhook失败:', error)
    ElMessage.error('配置Webhook失败')
  } finally {
    isConfiguringWebhook.value = false
  }
}



// 分析提交的真实分支归属
const analyzeCommitBranches = (commits, branches) => {
  console.log('开始分析提交的真实分支归属...')

  // 创建提交映射
  const commitMap = new Map()
  commits.forEach(commit => {
    commitMap.set(commit.id, commit)
  })

  // 根据你的git log输出，我们知道真实的分支结构
  // 2c73632 - Merge branch 'test_branch' (master分支的合并提交)
  // f7f39f3 - test_branch (test_branch分支的提交)
  // 3d5c7db - v1.7 (test2_branch分支的提交)
  // 2aeacfd - v1.5 (master分支的提交)
  // dfa56a4 - test (master分支的提交)

  commits.forEach(commit => {
    // 根据提交信息判断真实分支
    if (commit.title && commit.title.includes('Merge branch')) {
      // 合并提交属于目标分支（通常是master）
      commit.branch = 'master'
    } else if (commit.title && commit.title.includes('test_branch')) {
      // 包含test_branch的提交
      commit.branch = 'test_branch'
    } else if (commit.title && (commit.title.includes('v1.7') || commit.title.includes('test2'))) {
      // v1.7或包含test2的提交
      commit.branch = 'test2_branch'
    } else if (commit.parent_ids && commit.parent_ids.length === 1) {
      // 单父提交，检查父提交的分支
      const parentCommit = commitMap.get(commit.parent_ids[0])
      if (parentCommit && parentCommit.branch && parentCommit.branch !== 'master') {
        commit.branch = parentCommit.branch
      }
    }

    console.log(`提交 ${commit.short_id} (${commit.title}) -> 分支: ${commit.branch}`)
  })

  return commits
}

// 创建测试Git数据来演示GitFlow效果
const createTestGitData = () => {
  const now = new Date()

  // 创建一个完整的GitFlow示例
  const commits = [
    // 主分支初始提交
    {
      id: 'test_commit1',
      short_id: 'abc1234',
      title: 'Initial commit',
      message: 'Initial commit',
      author_name: 'Developer',
      created_at: new Date(now.getTime() - 10 * 24 * 60 * 60 * 1000).toISOString(),
      parent_ids: [],
      branch: 'master'
    },
    // 主分支第二个提交
    {
      id: 'test_commit2',
      short_id: 'def5678',
      title: 'Add basic structure',
      message: 'Add basic project structure',
      author_name: 'Developer',
      created_at: new Date(now.getTime() - 9 * 24 * 60 * 60 * 1000).toISOString(),
      parent_ids: ['test_commit1'],
      branch: 'master'
    },
    // 功能分支开始
    {
      id: 'test_commit3',
      short_id: 'ghi9012',
      title: 'Start feature development',
      message: 'Start feature development',
      author_name: 'Developer',
      created_at: new Date(now.getTime() - 8 * 24 * 60 * 60 * 1000).toISOString(),
      parent_ids: ['test_commit2'],
      branch: 'feature/user-auth'
    },
    // 功能分支继续开发
    {
      id: 'test_commit4',
      short_id: 'jkl3456',
      title: 'Add login functionality',
      message: 'Add user login functionality',
      author_name: 'Developer',
      created_at: new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000).toISOString(),
      parent_ids: ['test_commit3'],
      branch: 'feature/user-auth'
    },
    // 主分支继续开发
    {
      id: 'test_commit5',
      short_id: 'mno7890',
      title: 'Fix main branch issue',
      message: 'Fix critical issue in main branch',
      author_name: 'Developer',
      created_at: new Date(now.getTime() - 6 * 24 * 60 * 60 * 1000).toISOString(),
      parent_ids: ['test_commit2'],
      branch: 'master'
    },
    // 功能分支合并回主分支
    {
      id: 'test_commit6',
      short_id: 'pqr1234',
      title: 'Merge feature/user-auth',
      message: 'Merge branch feature/user-auth into master',
      author_name: 'Developer',
      created_at: new Date(now.getTime() - 5 * 24 * 60 * 60 * 1000).toISOString(),
      parent_ids: ['test_commit5', 'test_commit4'], // 合并提交有两个父提交
      branch: 'master'
    },
    // 新的功能分支
    {
      id: 'test_commit7',
      short_id: 'stu5678',
      title: 'Start API development',
      message: 'Start API development',
      author_name: 'Developer',
      created_at: new Date(now.getTime() - 4 * 24 * 60 * 60 * 1000).toISOString(),
      parent_ids: ['test_commit6'],
      branch: 'feature/api'
    },
    // API分支开发
    {
      id: 'test_commit8',
      short_id: 'vwx9012',
      title: 'Add REST endpoints',
      message: 'Add REST API endpoints',
      author_name: 'Developer',
      created_at: new Date(now.getTime() - 3 * 24 * 60 * 60 * 1000).toISOString(),
      parent_ids: ['test_commit7'],
      branch: 'feature/api'
    },
    // 主分支hotfix
    {
      id: 'test_commit9',
      short_id: 'yza3456',
      title: 'Hotfix: security patch',
      message: 'Critical security patch',
      author_name: 'Developer',
      created_at: new Date(now.getTime() - 2 * 24 * 60 * 60 * 1000).toISOString(),
      parent_ids: ['test_commit6'],
      branch: 'hotfix/security'
    },
    // Hotfix合并
    {
      id: 'test_commit10',
      short_id: 'bcd7890',
      title: 'Merge hotfix/security',
      message: 'Merge hotfix/security into master',
      author_name: 'Developer',
      created_at: new Date(now.getTime() - 1 * 24 * 60 * 60 * 1000).toISOString(),
      parent_ids: ['test_commit6', 'test_commit9'], // 合并提交
      branch: 'master'
    }
  ]

  console.log('创建测试Git数据:', commits.length, '个提交')
  return commits
}

// 加载项目的Git图表
const loadProjectGitGraph = async () => {
  if (!selectedProject.value) {
    console.log('没有选择项目，跳过加载Git图表')
    return
  }

  isLoadingGraph.value = true
  try {
    console.log('开始加载项目Git图表:', selectedProject.value)
    console.log('当前项目列表:', projects.value)

    // 根据选择的项目ID查找对应的GitLab项目
    const project = projects.value.find(p => p.id == selectedProject.value)
    if (!project) {
      console.error('未找到对应的项目，项目ID:', selectedProject.value)
      console.error('可用项目:', projects.value.map(p => ({ id: p.id, name: p.name })))
      ElMessage.error('未找到对应的项目')
      return
    }

    console.log('找到项目:', project)

    // 首先获取所有分支
    console.log('开始获取分支列表...')
    const branchResponse = await gitlabProjectApi.getBranches(project.id)
    console.log('分支API响应:', branchResponse)

    const allBranches = branchResponse.data?.data || branchResponse.data || []
    console.log('获取到分支列表:', allBranches)

    if (allBranches.length === 0) {
      console.log('该项目没有分支')
      gitCommits.value = []
      return
    }

    // 获取所有分支的提交记录 - 改进版本
    const allCommits = []
    const commitMap = new Map() // 用于去重和建立关系
    const branchColors = {}
    const colors = ['#4CAF50', '#FF5722', '#2196F3', '#FF9800', '#E91E63', '#9C27B0', '#607D8B']

    // 优先获取默认分支的提交记录，然后获取其他分支
    const defaultBranch = allBranches.find(b => b.default) || allBranches[0]
    const otherBranches = allBranches.filter(b => !b.default)

    console.log('开始获取Git提交数据，分支列表:', allBranches.map(b => b.name))

    // 先处理默认分支
    if (defaultBranch) {
      branchColors[defaultBranch.name] = colors[0]

      try {
        console.log(`开始获取默认分支 ${defaultBranch.name} 的提交记录...`)
        const commitResponse = await gitlabProjectApi.getCommits(project.id, defaultBranch.name)
        console.log(`默认分支 ${defaultBranch.name} 的API响应:`, commitResponse)

        const commits = commitResponse.data?.data || commitResponse.data || []
        console.log(`默认分支 ${defaultBranch.name} 的提交数量:`, commits.length)

        // 为每个提交添加分支信息并存储到Map中
        commits.forEach(commit => {
          if (!commitMap.has(commit.id)) {
            commit.branch = defaultBranch.name
            commit.branchColor = branchColors[defaultBranch.name]
            commitMap.set(commit.id, commit)
            allCommits.push(commit)
          }
        })
      } catch (error) {
        console.warn(`获取默认分支 ${defaultBranch.name} 的提交记录失败:`, error)
      }
    }

    // 再处理其他分支（限制最多5个其他分支）
    for (let i = 0; i < Math.min(otherBranches.length, 5); i++) {
      const branch = otherBranches[i]
      branchColors[branch.name] = colors[(i + 1) % colors.length]

      try {
        console.log(`开始获取分支 ${branch.name} 的提交记录...`)
        const commitResponse = await gitlabProjectApi.getCommits(project.id, branch.name)
        console.log(`分支 ${branch.name} 的API响应:`, commitResponse)

        const commits = commitResponse.data?.data || commitResponse.data || []
        console.log(`分支 ${branch.name} 的提交数量:`, commits.length)

        // 为每个提交添加分支信息，如果已存在则更新分支信息
        commits.forEach(commit => {
          if (!commitMap.has(commit.id)) {
            // 新提交，添加到列表
            commit.branch = branch.name
            commit.branchColor = branchColors[branch.name]
            commitMap.set(commit.id, commit)
            allCommits.push(commit)
            console.log(`新提交 ${commit.short_id} 来自分支 ${branch.name}`)
          } else {
            // 已存在的提交，可能是合并提交，保持原分支信息
            console.log(`提交 ${commit.short_id} 在多个分支中存在，当前分支: ${branch.name}`)

            // 如果是合并提交，优先使用主分支
            const existingCommit = commitMap.get(commit.id)
            if (branch.name === 'master' || branch.name === 'main') {
              existingCommit.branch = branch.name
              existingCommit.branchColor = branchColors[branch.name]
            }
          }
        })
      } catch (error) {
        console.warn(`获取分支 ${branch.name} 的提交记录失败:`, error)
      }
    }

    // 按时间排序所有提交，去重
    let uniqueCommits = []
    const commitIds = new Set()

    allCommits.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())

    allCommits.forEach(commit => {
      if (!commitIds.has(commit.id)) {
        commitIds.add(commit.id)
        uniqueCommits.push(commit)
      }
    })

    // 使用真实的Git数据
    console.log('使用真实Git数据，提交数量:', uniqueCommits.length)
    console.log('真实数据详情:', uniqueCommits.map(c => ({
      id: c.short_id,
      full_id: c.id,
      branch: c.branch,
      parents: c.parent_ids?.length || 0,
      parent_ids: c.parent_ids,
      title: c.title,
      isMerge: c.parent_ids?.length > 1
    })))

    // 分析合并提交
    const mergeCommits = uniqueCommits.filter(c => c.parent_ids?.length > 1)
    console.log('发现的合并提交:', mergeCommits.map(c => ({
      id: c.short_id,
      title: c.title,
      parents: c.parent_ids,
      branch: c.branch
    })))

    // 重新分析提交的分支归属
    uniqueCommits = analyzeCommitBranches(uniqueCommits, allBranches)

    gitCommits.value = uniqueCommits
    console.log('最终提交记录数量:', gitCommits.value.length)
    console.log('所有分支:', allBranches.map(b => b.name))
    console.log('重新分析后的提交详情:', gitCommits.value.map(c => ({
      id: c.short_id,
      title: c.title,
      branch: c.branch,
      parents: c.parent_ids?.length || 0,
      isMerge: c.parent_ids?.length > 1
    })))

    // 渲染Git图表
    if (gitCommits.value.length > 0) {
      nextTick(() => {
        // 等待DOM更新后再次检查ref
        setTimeout(() => {
          renderAdvancedGitGraph()
        }, 100)
      })
    }

  } catch (error) {
    console.error('加载Git图表失败:', error)
    ElMessage.error(`加载Git图表失败: ${error.message || error}`)
  } finally {
    isLoadingGraph.value = false
  }
}



// 简化的Git图表渲染 - 先确保基本功能
const renderGitGraph = () => {
  console.log('=== 开始渲染Git图表 ===')
  console.log('gitGraphRef.value:', gitGraphRef.value)
  console.log('gitCommits.value.length:', gitCommits.value?.length)

  if (!gitGraphRef.value || !gitCommits.value || gitCommits.value.length === 0) {
    console.log('条件不满足，退出渲染')
    return
  }

  try {
    console.log('提交数据:', gitCommits.value.map(c => ({
      short_id: c.short_id,
      title: c.title,
      parent_ids: c.parent_ids,
      branch: c.branch
    })))

    // 清空之前的图表
    gitGraphRef.value.innerHTML = ''

    // 创建简单的HTML结构先测试
    const container = document.createElement('div')
    container.style.cssText = `
      width: 100%;
      height: ${Math.max(gitCommits.value.length * 80 + 100, 400)}px;
      position: relative;
      overflow: auto;
      background: transparent;
      border: 2px solid #a4f4ba;
      border-radius: 8px;
      padding: 20px;
    `

    // 添加标题
    const title = document.createElement('div')
    title.style.cssText = `
      color: #fff;
      font-size: 18px;
      font-weight: bold;
      margin-bottom: 20px;
      text-align: center;
    `
    title.textContent = `Git 提交图表 (${gitCommits.value.length} 个提交)`
    container.appendChild(title)

    // 为每个提交创建简单的可视化
    gitCommits.value.forEach((commit, index) => {
      const commitDiv = document.createElement('div')
      const isMerge = commit.parent_ids && commit.parent_ids.length > 1
      const branch = commit.branch || 'master'

      // 分支颜色
      const branchColors = {
        'master': '#a4f4ba',
        'test_branch': '#ff6b6b',
        'test2_branch': '#4ecdc4'
      }
      const color = branchColors[branch] || '#67C23A'

      commitDiv.style.cssText = `
        display: flex;
        align-items: center;
        margin: 10px 0;
        padding: 10px;
        background: rgba(255,255,255,0.1);
        border-radius: 8px;
        border-left: 4px solid ${color};
      `

      // 节点圆圈
      const circle = document.createElement('div')
      circle.style.cssText = `
        width: ${isMerge ? '20px' : '16px'};
        height: ${isMerge ? '20px' : '16px'};
        border-radius: 50%;
        background: ${color};
        border: 2px solid #fff;
        margin-right: 15px;
        flex-shrink: 0;
        display: flex;
        align-items: center;
        justify-content: center;
        color: #fff;
        font-size: 10px;
        font-weight: bold;
      `
      if (isMerge) {
        circle.textContent = 'M'
      }

      // 提交信息
      const info = document.createElement('div')
      info.style.cssText = `
        color: #fff;
        flex: 1;
      `

      const operationType = isMerge ? '🔀 合并' : '📝 提交'
      info.innerHTML = `
        <div style="font-weight: bold; margin-bottom: 4px;">
          ${operationType}: ${commit.short_id} - ${commit.title}
        </div>
        <div style="font-size: 12px; opacity: 0.7;">
          🌿 ${branch} • ${commit.author_name} • ${new Date(commit.created_at).toLocaleString()}
        </div>
        ${isMerge ? `<div style="font-size: 11px; opacity: 0.6;">父提交: ${commit.parent_ids.map(id => id.substring(0, 8)).join(', ')}</div>` : ''}
      `

      commitDiv.appendChild(circle)
      commitDiv.appendChild(info)
      container.appendChild(commitDiv)

      console.log(`渲染提交 ${index + 1}/${gitCommits.value.length}: ${commit.short_id}`)
    })

    gitGraphRef.value.appendChild(container)
    console.log('=== Git图表渲染完成 ===')

  } catch (error) {
    console.error('Git图表渲染出错:', error)

    // 显示错误信息
    const errorDiv = document.createElement('div')
    errorDiv.style.cssText = `
      color: #ff6b6b;
      background: rgba(255, 107, 107, 0.1);
      border: 1px solid #ff6b6b;
      border-radius: 8px;
      padding: 20px;
      text-align: center;
    `
    errorDiv.innerHTML = `
      <h3>Git图表渲染失败</h3>
      <p>错误信息: ${error.message}</p>
      <p>请检查浏览器控制台获取详细信息</p>
    `
    gitGraphRef.value.appendChild(errorDiv)
  }
}



// 构建GitKraken风格的Git图结构
const buildGitKrakenGraph = (commits) => {
  const nodes = []
  const lines = []
  const branchLanes = new Map()
  const commitMap = new Map()

  // GitKraken风格的分支颜色
  const branchColors = {
    'master': '#a4f4ba',
    'main': '#a4f4ba',
    'test_branch': '#ff6b6b',
    'test2_branch': '#4ecdc4',
    'develop': '#45b7d1',
    'feature': '#96ceb4'
  }

  const laneWidth = 80
  const nodeSpacing = 70
  const baseX = 60

  console.log('开始构建Git图结构...')

  // 分析分支结构并分配车道
  let currentLane = 0
  commits.forEach(commit => {
    const branch = commit.branch || 'master'
    if (!branchLanes.has(branch)) {
      branchLanes.set(branch, currentLane++)
      console.log(`分支 ${branch} 分配到车道 ${branchLanes.get(branch)}`)
    }
  })

  // 创建节点
  commits.forEach((commit, index) => {
    const branch = commit.branch || 'master'
    const lane = branchLanes.get(branch)
    const x = baseX + lane * laneWidth
    const y = index * nodeSpacing + 60
    const color = branchColors[branch] || '#67C23A'

    const node = {
      x,
      y,
      commit,
      color,
      branch,
      lane
    }

    nodes.push(node)
    commitMap.set(commit.id, node)

    console.log(`节点 ${commit.short_id}: 位置(${x}, ${y}), 分支: ${branch}, 车道: ${lane}`)
  })

  // 创建连接线
  commits.forEach((commit, index) => {
    const currentNode = commitMap.get(commit.id)
    if (!currentNode || !commit.parent_ids || commit.parent_ids.length === 0) return

    const isMerge = commit.parent_ids.length > 1
    console.log(`处理提交 ${commit.short_id}, 父提交数量: ${commit.parent_ids.length}, 是否合并: ${isMerge}`)

    commit.parent_ids.forEach((parentId, parentIndex) => {
      const parentNode = commitMap.get(parentId)
      if (!parentNode) {
        console.log(`找不到父节点: ${parentId}`)
        return
      }

      const color = branchColors[currentNode.branch] || '#67C23A'
      const isMergeLine = isMerge && parentIndex > 0
      const width = isMergeLine ? 4 : 3

      console.log(`创建连线: ${currentNode.commit.short_id} -> ${parentNode.commit.short_id}, 合并线: ${isMergeLine}`)

      if (currentNode.lane === parentNode.lane) {
        // 同一车道的直线连接
        lines.push({
          type: 'line',
          startX: currentNode.x,
          startY: currentNode.y - 12,
          endX: parentNode.x,
          endY: parentNode.y + 12,
          color,
          width,
          isDashed: false
        })
      } else {
        // 不同车道的曲线连接（合并线）
        const midY = (currentNode.y + parentNode.y) / 2
        lines.push({
          type: 'curve',
          startX: currentNode.x,
          startY: currentNode.y - 12,
          cp1X: currentNode.x,
          cp1Y: midY,
          cp2X: parentNode.x,
          cp2Y: midY,
          endX: parentNode.x,
          endY: parentNode.y + 12,
          color,
          width,
          isDashed: isMergeLine
        })
      }
    })
  })

  console.log(`构建完成: ${nodes.length} 个节点, ${lines.length} 条连线`)
  return { nodes, lines }
}

const syncHistoryData = async () => {
  try {
    ElMessage.info('开始同步GitLab历史数据...')

    // 调用后端API同步历史数据
    const response = await gitlabServerApi.syncHistoryData()

    if (response.data?.success) {
      ElMessage.success('历史数据同步成功')
      // 重新加载审计数据
      loadAudits()
    } else {
      ElMessage.error(response.data?.message || '同步历史数据失败')
    }
  } catch (error) {
    console.error('同步历史数据失败:', error)
    ElMessage.error('同步历史数据失败')
  }
}

// 项目选择变化处理
const onProjectChange = (value) => {
  console.log('项目选择变化:', value)
  console.log('当前项目列表:', projects.value)

  // 重置分页
  pagination.value.current = 1

  // 重新加载审计数据
  loadAudits()

  // 如果选择了项目，加载Git图表
  if (value) {
    console.log('项目选择变化，开始加载Git图表，项目ID:', value)
    loadProjectGitGraph()
  } else {
    // 清空图表
    console.log('清空项目选择，清空Git图表')
    gitCommits.value = []
    if (gitGraphRef.value) {
      gitGraphRef.value.innerHTML = ''
    }
  }
}

// 生命周期
onMounted(() => {
  loadAudits()
  loadProjects()

  // 监听过滤条件变化，自动重新加载数据（排除项目选择，因为已经在onProjectChange中处理）
  watch([selectedOperation, selectedResult, dateRange], () => {
    pagination.value.current = 1
    loadAudits()
  }, { deep: true })

  // 搜索防抖
  let searchTimeout: any = null
  watch(searchText, () => {
    if (searchTimeout) {
      clearTimeout(searchTimeout)
    }
    searchTimeout = setTimeout(() => {
      pagination.value.current = 1
      loadAudits()
    }, 500)
  })
})

// GitKraken/GitFlow风格 - 多车道并行，斜线连接
const renderAdvancedGitGraph = () => {
  console.log('=== 开始渲染GitKraken/GitFlow风格Git图表 ===')

  if (!gitGraphRef.value || !gitCommits.value || gitCommits.value.length === 0) {
    console.log('跳过渲染：条件不满足')
    return
  }

  try {
    // 清空之前的图表
    gitGraphRef.value.innerHTML = ''

    // 创建容器
    const container = document.createElement('div')
    container.style.cssText = `
      width: 100%;
      height: 500px;
      position: relative;
      overflow: auto;
      background: linear-gradient(135deg, rgba(164, 244, 186, 0.05) 0%, rgba(76, 175, 80, 0.05) 100%);
      border: 2px solid #a4f4ba;
      border-radius: 12px;
      padding: 20px;
    `

    // 创建SVG
    const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
    const svgWidth = Math.max(gitCommits.value.length * 150 + 300, 1200)
    const svgHeight = 400

    svg.setAttribute('width', svgWidth)
    svg.setAttribute('height', svgHeight)
    svg.style.cssText = `
      width: ${svgWidth}px;
      height: ${svgHeight}px;
      background: transparent;
    `

    // GitFlow风格配置
    const branchColors = {
      'master': '#4CAF50',    // 绿色主分支
      'main': '#4CAF50',
      'test_branch': '#FF5722',  // 橙色分支
      'test2_branch': '#2196F3', // 蓝色分支
      'develop': '#9C27B0',      // 紫色分支
      'feature': '#00BCD4'       // 青色分支
    }

    // 分支车道配置 - 每个分支一个水平车道
    const laneHeight = 60    // 车道间距
    const nodeSpacing = 150  // 节点横向间距
    const startX = 150       // 起始X位置
    const startY = 100       // 起始Y位置

    // 重新分析分支结构 - 基于真实Git数据
    const branches = [...new Set(gitCommits.value.map(c => c.branch || 'master'))]
    const branchLanes = {}

    console.log('发现的所有分支:', branches)

    // 分析提交的分支分布
    const branchCommitCount = {}
    gitCommits.value.forEach(commit => {
      const branch = commit.branch || 'master'
      branchCommitCount[branch] = (branchCommitCount[branch] || 0) + 1
    })
    console.log('各分支提交分布:', branchCommitCount)

    // 主分支在中间（车道0）
    if (branches.includes('master')) {
      branchLanes['master'] = 0
    } else if (branches.includes('main')) {
      branchLanes['main'] = 0
    }

    // 其他分支分配车道 - test_branch在上方，test2_branch在下方
    let upperLane = -1
    let lowerLane = 1

    branches.forEach(branch => {
      if (branch !== 'master' && branch !== 'main' && !branchLanes[branch]) {
        if (branch.includes('test_branch')) {
          branchLanes[branch] = upperLane--
        } else {
          branchLanes[branch] = lowerLane++
        }
        console.log(`分支 ${branch} 分配到车道 ${branchLanes[branch]}`)
      }
    })

    console.log('分支车道分配:', branchLanes)
    console.log('提交数据详细分析:', gitCommits.value.map(c => ({
      id: c.short_id,
      full_id: c.id,
      branch: c.branch,
      parents: c.parent_ids?.length || 0,
      parent_ids: c.parent_ids,
      isMerge: c.parent_ids?.length > 1,
      title: c.title
    })))

    // 检查是否有多个分支的数据
    const branchStats = {}
    gitCommits.value.forEach(c => {
      const branch = c.branch || 'master'
      branchStats[branch] = (branchStats[branch] || 0) + 1
    })
    console.log('各分支提交数量统计:', branchStats)

    // 确保至少有2个分支用于演示
    if (Object.keys(branchStats).length < 2) {
      console.warn('只有一个分支，GitFlow效果无法展示')
    }

    // 构建节点位置 - 修复版本
    const nodes = gitCommits.value.map((commit, index) => {
      const branch = commit.branch || 'master'
      const lane = branchLanes[branch] !== undefined ? branchLanes[branch] : 0
      const x = startX + index * nodeSpacing
      const y = startY + lane * laneHeight
      const color = branchColors[branch] || '#67C23A'

      console.log(`节点 ${commit.short_id}: 分支=${branch}, 车道=${lane}, 位置=(${x}, ${y})`)

      return {
        commit,
        x,
        y,
        color,
        branch,
        lane,
        index,
        isMerge: commit.parent_ids && commit.parent_ids.length > 1
      }
    })

    // 创建提交映射
    const commitToNode = {}
    nodes.forEach(node => {
      commitToNode[node.commit.id] = node
    })
    // 绘制GitFlow风格的分支线条
    console.log('开始绘制GitFlow风格分支线条...')

    // 1. 绘制每个分支的水平线条
    Object.entries(branchLanes).forEach(([branch, lane]) => {
      const branchNodes = nodes.filter(n => n.branch === branch).sort((a, b) => a.index - b.index)
      const color = branchColors[branch] || '#67C23A'

      if (branchNodes.length > 1) {
        for (let i = 0; i < branchNodes.length - 1; i++) {
          const currentNode = branchNodes[i]
          const nextNode = branchNodes[i + 1]

          // 绘制同一分支内的水平连线
          const line = document.createElementNS('http://www.w3.org/2000/svg', 'line')
          line.setAttribute('x1', currentNode.x + 15)
          line.setAttribute('y1', currentNode.y)
          line.setAttribute('x2', nextNode.x - 15)
          line.setAttribute('y2', nextNode.y)
          line.setAttribute('stroke', color)
          line.setAttribute('stroke-width', '4')
          line.setAttribute('opacity', '0.8')
          svg.appendChild(line)
        }
      }
    })

    // 2. 绘制跨分支的连接线（分支分出和合并）
    nodes.forEach((node, index) => {
      const commit = node.commit

      if (commit.parent_ids && commit.parent_ids.length > 0) {
        commit.parent_ids.forEach((parentId, parentIndex) => {
          const parentNode = commitToNode[parentId]
          if (!parentNode) return

          // 跳过同一分支内的连接（已经绘制了水平线）
          if (node.lane === parentNode.lane) return

          const isMergeLine = commit.parent_ids.length > 1 && parentIndex > 0

          console.log(`跨分支连线: ${commit.short_id}(车道${node.lane}) -> ${parentNode.commit.short_id}(车道${parentNode.lane})`)

          // 绘制斜线连接不同车道
          const line = document.createElementNS('http://www.w3.org/2000/svg', 'line')
          line.setAttribute('x1', parentNode.x)
          line.setAttribute('y1', parentNode.y)
          line.setAttribute('x2', node.x)
          line.setAttribute('y2', node.y)

          if (isMergeLine) {
            // 合并线：虚线，红色
            line.setAttribute('stroke', '#FF5722')
            line.setAttribute('stroke-width', '3')
            line.setAttribute('stroke-dasharray', '8,4')
            line.setAttribute('opacity', '0.9')
          } else {
            // 分支线：实线，使用目标分支颜色
            line.setAttribute('stroke', node.color)
            line.setAttribute('stroke-width', '3')
            line.setAttribute('opacity', '0.7')
          }

          svg.appendChild(line)
        })
      }
    })

    // 3. 绘制分支标签（在左侧）
    console.log('绘制分支标签...')
    Object.entries(branchLanes).forEach(([branch, lane]) => {
      const y = startY + lane * laneHeight
      const color = branchColors[branch] || '#67C23A'

      // 分支标签背景
      const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
      rect.setAttribute('x', '10')
      rect.setAttribute('y', y - 12)
      rect.setAttribute('width', '120')
      rect.setAttribute('height', '24')
      rect.setAttribute('fill', color)
      rect.setAttribute('opacity', '0.2')
      rect.setAttribute('rx', '12')
      svg.appendChild(rect)

      // 分支标签文字
      const text = document.createElementNS('http://www.w3.org/2000/svg', 'text')
      text.setAttribute('x', '70')
      text.setAttribute('y', y + 5)
      text.setAttribute('text-anchor', 'middle')
      text.setAttribute('fill', color)
      text.setAttribute('font-size', '12')
      text.setAttribute('font-weight', 'bold')
      text.textContent = branch
      svg.appendChild(text)
    })

    // 4. 绘制提交节点（圆点）
    console.log('开始绘制提交节点...')
    nodes.forEach(node => {
      const commit = node.commit
      const radius = node.isMerge ? 10 : 8

      // 绘制节点圆圈
      const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle')
      circle.setAttribute('cx', node.x)
      circle.setAttribute('cy', node.y)
      circle.setAttribute('r', radius)
      circle.setAttribute('fill', node.color)
      circle.setAttribute('stroke', '#fff')
      circle.setAttribute('stroke-width', '3')
      circle.style.cursor = 'pointer'
      circle.style.filter = `drop-shadow(0 4px 8px ${node.color}60)`

      // 悬浮效果 - GitKraken风格
      circle.addEventListener('mouseenter', (e) => {
        // 放大节点
        circle.setAttribute('r', radius + 3)

        // 创建悬浮信息框
        const tooltip = document.createElement('div')
        tooltip.id = 'git-tooltip'
        tooltip.style.cssText = `
          position: absolute;
          background: rgba(0, 0, 0, 0.9);
          color: #fff;
          padding: 12px;
          border-radius: 8px;
          font-size: 12px;
          z-index: 1000;
          max-width: 300px;
          border: 1px solid ${node.color};
          box-shadow: 0 8px 32px rgba(0,0,0,0.3);
        `

        const operationType = node.isMerge ? '🔀 分支合并' : '📝 代码提交'
        const parentInfo = node.isMerge ? `<br><small>父提交: ${commit.parent_ids.map(id => id.substring(0, 8)).join(', ')}</small>` : ''

        tooltip.innerHTML = `
          <div style="font-weight: bold; color: ${node.color};">${operationType}</div>
          <div style="margin: 4px 0;"><strong>${commit.short_id}</strong> - ${commit.title}</div>
          <div style="font-size: 11px; opacity: 0.8;">
            🌿 ${node.branch}<br>
            👤 ${commit.author_name}<br>
            🕒 ${new Date(commit.created_at).toLocaleString()}
            ${parentInfo}
          </div>
        `

        // 定位悬浮框
        const rect = svg.getBoundingClientRect()
        tooltip.style.left = (rect.left + node.x + 20) + 'px'
        tooltip.style.top = (rect.top + node.y - 50) + 'px'

        document.body.appendChild(tooltip)
      })

      circle.addEventListener('mouseleave', () => {
        circle.setAttribute('r', radius)
        const tooltip = document.getElementById('git-tooltip')
        if (tooltip) {
          tooltip.remove()
        }
      })

      // 点击事件
      circle.addEventListener('click', () => {
        selectedCommit.value = commit
        console.log('选中提交:', commit.short_id)

        // 高亮选中的节点
        svg.querySelectorAll('circle').forEach(c => {
          c.setAttribute('stroke-width', '3')
        })
        circle.setAttribute('stroke-width', '5')
      })

      svg.appendChild(circle)

      // 如果是合并节点，添加M标记
      if (node.isMerge) {
        const text = document.createElementNS('http://www.w3.org/2000/svg', 'text')
        text.setAttribute('x', node.x)
        text.setAttribute('y', node.y + 3)
        text.setAttribute('text-anchor', 'middle')
        text.setAttribute('fill', '#fff')
        text.setAttribute('font-size', '8')
        text.setAttribute('font-weight', 'bold')
        text.textContent = 'M'
        svg.appendChild(text)
      }

      // 添加提交ID标签（在节点下方）
      const idText = document.createElementNS('http://www.w3.org/2000/svg', 'text')
      idText.setAttribute('x', node.x)
      idText.setAttribute('y', node.y + 25)
      idText.setAttribute('text-anchor', 'middle')
      idText.setAttribute('fill', '#fff')
      idText.setAttribute('font-size', '10')
      idText.setAttribute('font-weight', 'bold')
      idText.textContent = commit.short_id
      svg.appendChild(idText)
    })



    container.appendChild(svg)
    gitGraphRef.value.appendChild(container)
    console.log('=== GitKraken风格Git图表渲染完成！横向时间线+分支线条 ===')

  } catch (error) {
    console.error('Git图表渲染出错:', error)

    // 显示错误信息
    const errorDiv = document.createElement('div')
    errorDiv.style.cssText = `
      color: #ff6b6b;
      background: rgba(255, 107, 107, 0.1);
      border: 2px solid #ff6b6b;
      border-radius: 12px;
      padding: 20px;
      text-align: center;
      margin: 20px;
    `
    errorDiv.innerHTML = `
      <h3 style="margin: 0 0 10px 0;">⚠️ Git图表渲染失败</h3>
      <p style="margin: 0;">错误信息: ${error.message}</p>
      <p style="margin: 10px 0 0 0; font-size: 12px; opacity: 0.7;">请检查浏览器控制台获取详细信息</p>
    `
    gitGraphRef.value.appendChild(errorDiv)
  }
}
</script>

<style scoped>
/* 使用与GitLab用户管理页面完全相同的样式 */
.gitlab-audit-container {
  min-height: 100vh;
  padding: 24px 24px 100px 24px;
  position: relative;
  overflow-x: hidden;
  background: transparent !important;
}

.starry-background {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: linear-gradient(135deg,
    rgba(0, 0, 0, 0.9) 0%,
    rgba(20, 20, 40, 0.95) 50%,
    rgba(0, 0, 0, 0.9) 100%
  );
  z-index: 0;
  pointer-events: none;
}

.stars, .stars2, .stars3 {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: transparent;
}

.stars {
  background-image:
    radial-gradient(2px 2px at 20px 30px, #eee, transparent),
    radial-gradient(2px 2px at 40px 70px, rgba(255,255,255,0.8), transparent),
    radial-gradient(1px 1px at 90px 40px, #fff, transparent);
  background-repeat: repeat;
  background-size: 200px 100px;
  animation: zoom 20s infinite linear;
}

.stars2 {
  background-image:
    radial-gradient(1px 1px at 40px 60px, #fff, transparent),
    radial-gradient(1px 1px at 120px 10px, rgba(255,255,255,0.7), transparent);
  background-repeat: repeat;
  background-size: 300px 200px;
  animation: zoom 40s infinite linear;
}

.stars3 {
  background-image:
    radial-gradient(1px 1px at 10px 10px, rgba(255,255,255,0.5), transparent);
  background-repeat: repeat;
  background-size: 400px 300px;
  animation: zoom 60s infinite linear;
}

@keyframes zoom {
  from { transform: scale(1); }
  to { transform: scale(1.5); }
}

@keyframes twinkle {
  0% { opacity: 0.3; }
  100% { opacity: 1; }
}

.glass-container {
  background: rgba(164, 244, 186, 0.1);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(164, 244, 186, 0.2);
  border-radius: 16px;
  padding: 24px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}

/* 按钮样式 - 完全照抄GitLab用户管理页面 */
.glass-button {
  background: rgba(164, 244, 186, 0.15);
  border: 1px solid rgba(164, 244, 186, 0.4);
  border-radius: 8px;
  color: #a4f4ba;
  padding: 8px 16px;
  cursor: pointer;
  transition: all 0.3s ease;
  font-size: 14px;
  font-weight: 500;
  display: flex;
  align-items: center;
  gap: 8px;
  backdrop-filter: blur(5px);
  box-shadow: 0 4px 15px rgba(164, 244, 186, 0.1);
  position: relative;
  z-index: 1;
}

.glass-button:hover {
  background: rgba(164, 244, 186, 0.25);
  border-color: rgba(164, 244, 186, 0.6);
  color: #fff;
  transform: translateY(-2px);
  box-shadow: 0 6px 20px rgba(164, 244, 186, 0.2);
}

.glass-button.primary {
  background: rgba(164, 244, 186, 0.25);
  border-color: rgba(164, 244, 186, 0.6);
  color: #fff;
  box-shadow: 0 4px 15px rgba(164, 244, 186, 0.2);
}

.glass-button.small {
  padding: 4px 8px;
  font-size: 12px;
}

.glass-button.danger {
  background: rgba(255, 99, 99, 0.2);
  border-color: rgba(255, 99, 99, 0.3);
}

.glass-button.danger:hover {
  background: rgba(255, 99, 99, 0.3);
  border-color: rgba(255, 99, 99, 0.5);
}

/* 输入框样式 */
.glass-input {
  background: rgba(164, 244, 186, 0.1) !important;
  border: 1px solid rgba(164, 244, 186, 0.3) !important;
  border-radius: 8px !important;
  padding: 8px 12px !important;
  color: #fff !important;
  font-size: 14px !important;
  transition: all 0.3s ease !important;
  width: 100% !important;
  backdrop-filter: blur(10px) !important;
}

.glass-input:focus {
  outline: none !important;
  border-color: rgba(164, 244, 186, 0.5) !important;
  background: rgba(164, 244, 186, 0.15) !important;
}

.glass-input::placeholder {
  color: rgba(255, 255, 255, 0.5) !important;
}

/* 下拉菜单样式 */
.glass-select {
  background: rgba(164, 244, 186, 0.1) !important;
  border: 1px solid rgba(164, 244, 186, 0.3) !important;
  border-radius: 8px !important;
  padding: 8px 12px !important;
  color: #fff !important;
  font-size: 14px !important;
  transition: all 0.3s ease !important;
  backdrop-filter: blur(10px) !important;
  cursor: pointer !important;
}

.glass-select:focus {
  outline: none !important;
  border-color: rgba(164, 244, 186, 0.5) !important;
  background: rgba(164, 244, 186, 0.15) !important;
}

.glass-select option {
  background: rgba(20, 20, 40, 0.95) !important;
  color: #fff !important;
}

/* Element Plus 选择器样式覆盖 - 完全照抄GitLab用户管理页面 */
:deep(.el-select) {
  .el-input__wrapper {
    background: rgba(164, 244, 186, 0.1) !important;
    border: 1px solid rgba(164, 244, 186, 0.3) !important;
    border-radius: 8px !important;
    box-shadow: none !important;
  }

  .el-input__inner {
    background: transparent !important;
    color: #fff !important;
  }

  &:hover .el-input__wrapper {
    border-color: rgba(164, 244, 186, 0.5) !important;
  }

  &.is-focused .el-input__wrapper {
    border-color: rgba(164, 244, 186, 0.5) !important;
    background: rgba(164, 244, 186, 0.15) !important;
  }
}

:deep(.el-select-dropdown) {
  background: rgba(30, 30, 30, 0.95) !important;
  border: 1px solid rgba(164, 244, 186, 0.3) !important;
  border-radius: 8px !important;
}

:deep(.el-select-dropdown__item) {
  color: rgba(255, 255, 255, 0.8) !important;

  &:hover {
    background: rgba(164, 244, 186, 0.1) !important;
  }

  &.selected {
    background: rgba(164, 244, 186, 0.2) !important;
    color: #a4f4ba !important;
  }
}

:deep(.el-input) {
  .el-input__wrapper {
    background: rgba(164, 244, 186, 0.1) !important;
    border: 1px solid rgba(164, 244, 186, 0.3) !important;
    border-radius: 8px !important;
    box-shadow: none !important;
  }

  .el-input__inner {
    background: transparent !important;
    color: #fff !important;
  }

  &:hover .el-input__wrapper {
    border-color: rgba(164, 244, 186, 0.5) !important;
  }

  &.is-focus .el-input__wrapper {
    border-color: rgba(164, 244, 186, 0.5) !important;
    background: rgba(164, 244, 186, 0.15) !important;
  }
}

:deep(.el-select-dropdown) {
  background: rgba(30, 30, 30, 0.95) !important;
  border: 1px solid rgba(164, 244, 186, 0.3) !important;
  border-radius: 8px !important;
}

:deep(.el-select-dropdown__item) {
  color: rgba(255, 255, 255, 0.8) !important;

  &:hover {
    background: rgba(164, 244, 186, 0.1) !important;
  }

  &.selected {
    background: rgba(164, 244, 186, 0.2) !important;
    color: #a4f4ba !important;
  }
}

/* 日期选择器样式 */
:deep(.el-date-picker) {
  width: 100% !important;
}

:deep(.glass-date-picker) {
  width: 100% !important;

  .el-input__wrapper {
    background: rgba(164, 244, 186, 0.1) !important;
    border: 1px solid rgba(164, 244, 186, 0.3) !important;
    border-radius: 8px !important;
    box-shadow: none !important;
    padding: 0 12px !important;
  }

  .el-input__inner {
    background: transparent !important;
    color: #fff !important;
    border: none !important;
    outline: none !important;
    box-shadow: none !important;
  }

  &:hover .el-input__wrapper {
    border-color: rgba(164, 244, 186, 0.5) !important;
    box-shadow: none !important;
  }

  &.is-focus .el-input__wrapper {
    border-color: rgba(164, 244, 186, 0.5) !important;
    background: rgba(164, 244, 186, 0.15) !important;
    box-shadow: none !important;
  }
}

/* 日期选择器弹出面板样式 */
:deep(.el-picker-panel) {
  background: rgba(30, 30, 30, 0.95) !important;
  border: 1px solid rgba(164, 244, 186, 0.3) !important;
  border-radius: 8px !important;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3) !important;
}

:deep(.el-picker-panel__body) {
  background: transparent !important;
}

:deep(.el-date-table th) {
  color: rgba(255, 255, 255, 0.7) !important;
  background: transparent !important;
}

:deep(.el-date-table td) {
  color: rgba(255, 255, 255, 0.8) !important;
}

:deep(.el-date-table td.available:hover) {
  background: rgba(164, 244, 186, 0.1) !important;
  color: #a4f4ba !important;
}

:deep(.el-date-table td.current:not(.disabled)) {
  background: rgba(164, 244, 186, 0.2) !important;
  color: #a4f4ba !important;
}

:deep(.el-picker-panel__header) {
  color: #a4f4ba !important;
  background: transparent !important;
}

:deep(.el-picker-panel__header button) {
  color: rgba(255, 255, 255, 0.7) !important;
}

:deep(.el-picker-panel__header button:hover) {
  color: #a4f4ba !important;
}

/* Webhook配置弹窗样式 */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.7);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.modal-content {
  background: rgba(164, 244, 186, 0.1);
  backdrop-filter: blur(15px);
  border: 1px solid rgba(164, 244, 186, 0.3);
  border-radius: 16px;
  padding: 24px;
  max-width: 1000px;
  width: 95%;
  max-height: 85vh;
  overflow-y: auto;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  padding-bottom: 15px;
  border-bottom: 1px solid rgba(164, 244, 186, 0.2);
}

.graph-controls {
  display: flex;
  gap: 16px;
  align-items: center;
}

.graph-controls .glass-select {
  min-width: 200px;
}

.graph-controls :deep(.el-select) {
  min-width: 200px;
}

.graph-controls :deep(.el-input__wrapper) {
  min-width: 200px;
  width: 200px;
}

.modal-header h3 {
  color: #a4f4ba;
  margin: 0;
  font-size: 18px;
  font-weight: 600;
}

.close-btn {
  background: none;
  border: none;
  color: rgba(255, 255, 255, 0.7);
  font-size: 18px;
  cursor: pointer;
  padding: 5px;
  border-radius: 4px;
  transition: all 0.3s ease;
}

.close-btn:hover {
  color: #fff;
  background: rgba(255, 255, 255, 0.1);
}

.webhook-info {
  margin-bottom: 20px;
}

.webhook-info h4 {
  color: #a4f4ba;
  margin-bottom: 10px;
}

.webhook-info p {
  color: rgba(255, 255, 255, 0.8);
  margin-bottom: 10px;
}

.webhook-info ul {
  color: rgba(255, 255, 255, 0.8);
  padding-left: 20px;
}

.webhook-info li {
  margin-bottom: 5px;
}

.server-selection {
  margin-bottom: 20px;
}

.server-selection label {
  display: block;
  color: #a4f4ba;
  margin-bottom: 8px;
  font-weight: 500;
}

.webhook-url-info {
  margin-bottom: 20px;
}

.webhook-url-info label {
  display: block;
  color: #a4f4ba;
  margin-bottom: 8px;
  font-weight: 500;
}

.url-display {
  display: flex;
  gap: 10px;
  align-items: center;
}

.url-display input {
  flex: 1;
}

.webhook-actions {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}

.manual-config {
  background: rgba(164, 244, 186, 0.05);
  border: 1px solid rgba(164, 244, 186, 0.2);
  border-radius: 8px;
  padding: 15px;
  margin-bottom: 20px;
}

.manual-config h4 {
  color: #a4f4ba;
  margin-bottom: 10px;
}

.manual-config ol {
  color: rgba(255, 255, 255, 0.8);
  padding-left: 20px;
}

.manual-config li {
  margin-bottom: 8px;
}

.manual-config code {
  background: rgba(164, 244, 186, 0.1);
  color: #a4f4ba;
  padding: 2px 6px;
  border-radius: 4px;
  font-family: 'Courier New', monospace;
}

.webhook-results {
  background: rgba(164, 244, 186, 0.05);
  border: 1px solid rgba(164, 244, 186, 0.2);
  border-radius: 8px;
  padding: 15px;
}

.webhook-results h4 {
  color: #a4f4ba;
  margin-bottom: 10px;
}

.result-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px;
  margin-bottom: 5px;
  border-radius: 4px;
}

.result-item.success {
  background: rgba(76, 175, 80, 0.1);
  color: #4caf50;
}

.result-item.error {
  background: rgba(244, 67, 54, 0.1);
  color: #f44336;
}

.glass-button.primary {
  background: rgba(164, 244, 186, 0.25) !important;
  border-color: rgba(164, 244, 186, 0.6) !important;
  color: #fff !important;
  box-shadow: 0 4px 15px rgba(164, 244, 186, 0.2) !important;
}

.glass-button:disabled {
  opacity: 0.5 !important;
  cursor: not-allowed !important;
}

/* Git图表弹窗样式 */
.git-graph-modal {
  max-width: 1200px;
  width: 95%;
  max-height: 90vh;
}

.graph-controls {
  display: flex;
  gap: 10px;
  align-items: center;
}

.git-graph-body {
  max-height: 70vh;
  overflow-y: auto;
}

.git-graph-container {
  display: flex;
  gap: 20px;
  height: 100%;
}

.git-graph {
  flex: 2;
  background: rgba(164, 244, 186, 0.05);
  border: 1px solid rgba(164, 244, 186, 0.2);
  border-radius: 8px;
  padding: 15px;
  overflow-x: auto;
  min-height: 400px;
}

.commit-details {
  flex: 1;
  background: rgba(164, 244, 186, 0.05);
  border: 1px solid rgba(164, 244, 186, 0.2);
  border-radius: 8px;
  padding: 15px;
}

.commit-details h4 {
  color: #a4f4ba;
  margin-bottom: 15px;
  font-size: 16px;
}

.commit-info {
  color: rgba(255, 255, 255, 0.9);
}

.commit-header {
  margin-bottom: 10px;
}

.commit-title {
  font-size: 16px;
  font-weight: 600;
  margin-bottom: 5px;
  color: #fff;
}

.commit-meta {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.7);
}

.commit-id {
  font-family: 'Courier New', monospace;
  background: rgba(164, 244, 186, 0.1);
  padding: 2px 6px;
  border-radius: 4px;
  color: #a4f4ba;
}

.commit-message {
  margin: 10px 0;
  padding: 10px;
  background: rgba(164, 244, 186, 0.05);
  border-radius: 4px;
  font-size: 14px;
  line-height: 1.4;
  white-space: pre-wrap;
}

.file-stats {
  display: flex;
  gap: 10px;
  margin-top: 10px;
}

.additions {
  color: #4caf50;
  font-weight: 600;
}

.deletions {
  color: #f44336;
  font-weight: 600;
}

.no-selection {
  color: rgba(255, 255, 255, 0.5);
  text-align: center;
  padding: 40px 20px;
  font-style: italic;
}

.loading-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 60px 20px;
  color: rgba(255, 255, 255, 0.7);
  gap: 15px;
}

.loading-state i {
  font-size: 24px;
  color: #a4f4ba;
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 24px;
}

.page-title {
  color: #fff;
  font-size: 24px;
  font-weight: 600;
  margin: 0;
  display: flex;
  align-items: center;
  gap: 12px;
}

.header-actions {
  display: flex;
  gap: 12px;
}

/* 工具栏样式 */
.toolbar-section {
  margin-bottom: 20px;
  padding: 20px;
  border-radius: 12px;
}

.toolbar-buttons {
  display: flex;
  gap: 12px;
  align-items: center;
  flex-wrap: wrap;
}

.filters-section {
  margin-bottom: 30px;
  padding: 20px;
  border-radius: 12px;
}

.filters-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 20px;
  align-items: end;
}

.filter-item {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.filter-item label {
  color: #a4f4ba;
  font-size: 14px;
  font-weight: 500;
  margin-bottom: 5px;
}

.glass-input {
  background: rgba(164, 244, 186, 0.1);
  border: 1px solid rgba(164, 244, 186, 0.3);
  border-radius: 8px;
  padding: 8px 12px;
  color: #fff;
  font-size: 14px;
  transition: all 0.3s ease;
  width: 100%;
}

.glass-input:focus {
  outline: none;
  border-color: rgba(164, 244, 186, 0.5);
  background: rgba(164, 244, 186, 0.15);
}

.glass-input::placeholder {
  color: rgba(255, 255, 255, 0.5);
}

.glass-select {
  background: rgba(164, 244, 186, 0.1);
  border: 1px solid rgba(164, 244, 186, 0.3);
  border-radius: 8px;
  padding: 8px 12px;
  color: #fff;
  font-size: 14px;
  transition: all 0.3s ease;
  width: 100%;
}

.glass-select:focus {
  outline: none;
  border-color: rgba(164, 244, 186, 0.5);
  background: rgba(164, 244, 186, 0.15);
}

.glass-select option {
  background: #2a5298;
  color: #fff;
}

.audit-table {
  background: rgba(164, 244, 186, 0.05);
  border: 1px solid rgba(164, 244, 186, 0.2);
  border-radius: 12px;
  overflow: hidden;
  margin-bottom: 24px;
}

.table-header {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
  background: rgba(164, 244, 186, 0.1);
  border-bottom: 1px solid rgba(164, 244, 186, 0.2);
}

.header-cell {
  padding: 12px 8px;
  color: #fff;
  font-weight: 600;
  font-size: 14px;
}

.table-body {
  /* 移除固定高度和滚动条，让表格自然展示 */
}

.table-row {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
  border-bottom: 1px solid rgba(164, 244, 186, 0.1);
  transition: all 0.3s ease;
}

.table-row:hover {
  background: rgba(164, 244, 186, 0.05);
}

.table-row.row-success {
  border-left: 3px solid #51cf66;
}

.table-row.row-failed {
  border-left: 3px solid #ff6b6b;
}

.table-cell {
  padding: 8px;
  display: flex;
  align-items: center;
}

.time-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.time-primary {
  color: #fff;
  font-size: 13px;
  font-weight: 500;
}

.time-secondary {
  color: rgba(255, 255, 255, 0.6);
  font-size: 11px;
}

.operation-badge {
  padding: 4px 8px;
  border-radius: 4px;
  font-size: 11px;
  font-weight: 500;
  border: 1px solid;
}

.op-create {
  background: rgba(74, 222, 128, 0.2);
  color: #4ade80;
  border-color: rgba(74, 222, 128, 0.3);
}

.op-update {
  background: rgba(59, 130, 246, 0.2);
  color: #3b82f6;
  border-color: rgba(59, 130, 246, 0.3);
}

.op-delete {
  background: rgba(239, 68, 68, 0.2);
  color: #ef4444;
  border-color: rgba(239, 68, 68, 0.3);
}

.op-commit {
  background: rgba(168, 85, 247, 0.2);
  color: #a855f7;
  border-color: rgba(168, 85, 247, 0.3);
}

.op-merge {
  background: rgba(251, 191, 36, 0.2);
  color: #fbbf24;
  border-color: rgba(251, 191, 36, 0.3);
}

.op-sync {
  background: rgba(34, 197, 94, 0.2);
  color: #22c55e;
  border-color: rgba(34, 197, 94, 0.3);
}

.op-default {
  background: rgba(156, 163, 175, 0.2);
  color: #9ca3af;
  border-color: rgba(156, 163, 175, 0.3);
}

.user-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.username {
  color: #fff;
  font-size: 13px;
  font-weight: 500;
}

.user-name {
  color: rgba(255, 255, 255, 0.6);
  font-size: 11px;
}

.target-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.target-name {
  color: #fff;
  font-size: 13px;
  font-weight: 500;
  word-break: break-word;
}

.target-type {
  color: rgba(255, 255, 255, 0.6);
  font-size: 11px;
}

.project-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.project-name {
  color: rgba(255, 255, 255, 0.8);
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.project-path {
  color: rgba(255, 255, 255, 0.6);
  font-size: 11px;
  font-family: 'Courier New', monospace;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.result-badge {
  padding: 4px 8px;
  border-radius: 4px;
  font-size: 11px;
  font-weight: 500;
}

.result-success {
  background: rgba(74, 222, 128, 0.2);
  color: #4ade80;
  border: 1px solid rgba(74, 222, 128, 0.3);
}

.result-failed {
  background: rgba(239, 68, 68, 0.2);
  color: #ef4444;
  border: 1px solid rgba(239, 68, 68, 0.3);
}

.action-buttons {
  display: flex;
  gap: 6px;
  align-items: center;
  justify-content: flex-start;
  flex-wrap: nowrap;
}

/* Git图表样式 */
.git-graph-section {
  margin-bottom: 24px;
  border-radius: 12px;
  overflow: hidden;
  width: 100%;
}

.git-graph-section .section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 24px;
  border-bottom: 1px solid rgba(164, 244, 186, 0.2);
  background: rgba(164, 244, 186, 0.05);
}

.git-graph-section .section-header h3 {
  margin: 0;
  color: #fff;
  font-size: 20px;
  font-weight: 600;
}

.git-graph-section .section-header h3 i {
  margin-right: 10px;
  color: #a4f4ba;
}

.git-graph-container {
  padding: 24px;
  width: 100%;
}

.git-graph-content {
  background: rgba(0, 0, 0, 0.3);
  border-radius: 12px;
  padding: 24px;
  min-height: 400px;
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: flex-start;
}

.git-graph {
  width: 100%;
  min-height: 400px;
  overflow: auto;
  display: flex;
  justify-content: center;
}

.loading-state, .empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 300px;
  color: rgba(255, 255, 255, 0.7);
  text-align: center;
  width: 100%;
}

.loading-state i {
  font-size: 32px;
  margin-bottom: 16px;
  color: #a4f4ba;
}

.empty-state .empty-icon {
  font-size: 64px;
  margin-bottom: 20px;
  color: rgba(164, 244, 186, 0.5);
}

.empty-state h4 {
  margin: 0 0 12px 0;
  color: #fff;
  font-size: 18px;
  font-weight: 600;
}

.empty-state p {
  margin: 0;
  color: rgba(255, 255, 255, 0.6);
  font-size: 14px;
  max-width: 400px;
  line-height: 1.5;
}

.glass-button {
  background: rgba(164, 244, 186, 0.2);
  border: 1px solid rgba(164, 244, 186, 0.3);
  border-radius: 8px;
  color: #fff;
  padding: 8px 16px;
  cursor: pointer;
  transition: all 0.3s ease;
  font-size: 14px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.glass-button:hover {
  background: rgba(164, 244, 186, 0.3);
  border-color: rgba(164, 244, 186, 0.5);
  transform: translateY(-2px);
}

.glass-button.small {
  padding: 4px 8px;
  font-size: 12px;
}

.glass-button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
}

.empty-state {
  text-align: center;
  padding: 60px 20px;
  color: rgba(255, 255, 255, 0.7);
}

.empty-icon {
  font-size: 64px;
  margin-bottom: 16px;
  opacity: 0.5;
}

.empty-state h3 {
  color: #fff;
  margin-bottom: 8px;
}

.empty-state p {
  margin-bottom: 24px;
}

.pagination {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 24px;
}

.pagination-info {
  color: rgba(255, 255, 255, 0.7);
  font-size: 14px;
}

.pagination-controls {
  display: flex;
  gap: 8px;
}

/* 模态框样式 */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.modal-content {
  width: 90%;
  max-width: 800px;
  max-height: 90vh;
  overflow-y: auto;
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 24px;
}

.modal-header h3 {
  color: #fff;
  margin: 0;
}

.close-btn {
  background: none;
  border: none;
  color: rgba(255, 255, 255, 0.7);
  font-size: 18px;
  cursor: pointer;
  padding: 4px;
}

.close-btn:hover {
  color: #fff;
}

.audit-detail-content {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.detail-section h4 {
  color: #fff;
  margin: 0 0 16px 0;
  font-size: 16px;
}

.detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 16px;
}

.detail-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.detail-item .label {
  color: rgba(255, 255, 255, 0.7);
  font-size: 12px;
  font-weight: 500;
}

.detail-item .value {
  color: #fff;
  font-size: 14px;
}

.error-message {
  background: rgba(239, 68, 68, 0.1);
  border: 1px solid rgba(239, 68, 68, 0.3);
  border-radius: 8px;
  padding: 16px;
  color: #ef4444;
  font-size: 14px;
}

.detail-json {
  background: rgba(0, 0, 0, 0.2);
  border: 1px solid rgba(164, 244, 186, 0.2);
  border-radius: 8px;
  padding: 16px;
  color: rgba(255, 255, 255, 0.8);
  font-size: 12px;
  margin: 0;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 300px;
  overflow-y: auto;
}
</style>
